PersisterListenerCollection.java
package org.codefilarete.stalactite.engine.listener;
import java.util.Set;
import java.util.function.Supplier;
import org.codefilarete.stalactite.sql.ddl.structure.Table;
import org.codefilarete.tool.Duo;
import org.codefilarete.tool.collection.Iterables;
import org.codefilarete.tool.function.ThrowingExecutable;
import org.codefilarete.tool.function.ThrowingRunnable;
/**
* Simple class that centralizes persistence event listener registration as well as execution of some code wrapped between event triggering.
*
* @author Guillaume Mary
* @see #doWithInsertListener(Iterable, ThrowingExecutable)
* @see #doWithUpdateListener(Iterable, boolean, Supplier)
* @see #doWithUpdateByIdListener(Iterable, ThrowingExecutable)
* @see #doWithDeleteListener(Iterable, ThrowingExecutable)
* @see #doWithDeleteByIdListener(Iterable, ThrowingExecutable)
* @see #doWithSelectListener(Iterable, ThrowingExecutable)
*/
public class PersisterListenerCollection<C, I> implements PersisterListener<C, I> {
private final PersistListenerCollection<C> persistListener = new PersistListenerCollection<>();
private final InsertListenerCollection<C> insertListener = new InsertListenerCollection<>();
private final UpdateByIdListenerCollection<C> updateByIdListener = new UpdateByIdListenerCollection<>();
private final UpdateListenerCollection<C> updateListener = new UpdateListenerCollection<>();
private final DeleteListenerCollection<C> deleteListener = new DeleteListenerCollection<>();
private final DeleteByIdListenerCollection<C> deleteByIdListener = new DeleteByIdListenerCollection<>();
private final SelectListenerCollection<C, I> selectListener = new SelectListenerCollection<>();
public InsertListenerCollection<C> getInsertListener() {
return insertListener;
}
@Override
public void addPersistListener(PersistListener<? extends C> persistListener) {
this.persistListener.add(persistListener);
}
public <R> R doWithPersistListener(Iterable<? extends C> entities, ThrowingExecutable<R, RuntimeException> delegate) {
R result;
try {
persistListener.beforePersist(entities);
result = delegate.execute();
persistListener.afterPersist(entities);
} catch (RuntimeException e) {
persistListener.onPersistError(entities, e);
throw e;
}
return result;
}
public void doWithPersistListener(Iterable<? extends C> entities, ThrowingRunnable<RuntimeException> delegate) {
try {
persistListener.beforePersist(entities);
delegate.run();
persistListener.afterPersist(entities);
} catch (RuntimeException e) {
persistListener.onPersistError(entities, e);
throw e;
}
}
@Override
public void addInsertListener(InsertListener<? extends C> insertListener) {
this.insertListener.add(insertListener);
}
public <R> R doWithInsertListener(Iterable<? extends C> entities, ThrowingExecutable<R, RuntimeException> delegate) {
R result;
try {
insertListener.beforeInsert(entities);
result = delegate.execute();
insertListener.afterInsert(entities);
} catch (RuntimeException e) {
insertListener.onInsertError(entities, e);
throw e;
}
return result;
}
public void doWithInsertListener(Iterable<? extends C> entities, ThrowingRunnable<RuntimeException> delegate) {
try {
insertListener.beforeInsert(entities);
delegate.run();
insertListener.afterInsert(entities);
} catch (RuntimeException e) {
insertListener.onInsertError(entities, e);
throw e;
}
}
public UpdateByIdListenerCollection<C> getUpdateByIdListener() {
return updateByIdListener;
}
@Override
public void addUpdateByIdListener(UpdateByIdListener<? extends C> updateByIdListener) {
this.updateByIdListener.add((UpdateByIdListener<C>) updateByIdListener);
}
public <R> R doWithUpdateByIdListener(Iterable<? extends C> entities, ThrowingExecutable<R, RuntimeException> delegate) {
R result;
try {
updateByIdListener.beforeUpdateById(entities);
result = delegate.execute();
updateByIdListener.afterUpdateById(entities);
} catch (RuntimeException e) {
updateByIdListener.onUpdateError(entities, e);
throw e;
}
return result;
}
public void doWithUpdateByIdListener(Iterable<? extends C> entities, ThrowingRunnable<RuntimeException> delegate) {
try {
updateByIdListener.beforeUpdateById(entities);
delegate.run();
updateByIdListener.afterUpdateById(entities);
} catch (RuntimeException e) {
updateByIdListener.onUpdateError(entities, e);
throw e;
}
}
public UpdateListenerCollection<C> getUpdateListener() {
return updateListener;
}
@Override
public void addUpdateListener(UpdateListener<? extends C> updateListener) {
this.updateListener.add((UpdateListener<C>) updateListener);
}
public <R, T extends Table<T>> R doWithUpdateListener(Iterable<? extends Duo<C, C>> differencesIterable, boolean allColumnsStatement,
Supplier<R> delegate) {
R result;
try {
updateListener.beforeUpdate(differencesIterable, allColumnsStatement);
result = delegate.get();
updateListener.afterUpdate(differencesIterable, allColumnsStatement);
} catch (RuntimeException e) {
updateListener.onUpdateError(Iterables.collectToList(differencesIterable, Duo::getLeft), e);
throw e;
}
return result;
}
public <T extends Table<T>> void doWithUpdateListener(Iterable<? extends Duo<C, C>> differencesIterable, boolean allColumnsStatement,
Runnable delegate) {
try {
updateListener.beforeUpdate(differencesIterable, allColumnsStatement);
delegate.run();
updateListener.afterUpdate(differencesIterable, allColumnsStatement);
} catch (RuntimeException e) {
updateListener.onUpdateError(Iterables.collectToList(differencesIterable, Duo::getLeft), e);
throw e;
}
}
public DeleteListenerCollection<C> getDeleteListener() {
return deleteListener;
}
public DeleteByIdListenerCollection<C> getDeleteByIdListener() {
return deleteByIdListener;
}
@Override
public void addDeleteListener(DeleteListener<? extends C> deleteListener) {
this.deleteListener.add(deleteListener);
}
public <R> R doWithDeleteListener(Iterable<? extends C> entities, ThrowingExecutable<R, RuntimeException> delegate) {
R result;
try {
deleteListener.beforeDelete(entities);
result = delegate.execute();
deleteListener.afterDelete(entities);
} catch (RuntimeException e) {
deleteListener.onDeleteError(entities, e);
throw e;
}
return result;
}
public void doWithDeleteListener(Iterable<? extends C> entities, ThrowingRunnable<RuntimeException> delegate) {
try {
deleteListener.beforeDelete(entities);
delegate.run();
deleteListener.afterDelete(entities);
} catch (RuntimeException e) {
deleteListener.onDeleteError(entities, e);
throw e;
}
}
@Override
public void addDeleteByIdListener(DeleteByIdListener<? extends C> deleteByIdListener) {
this.deleteByIdListener.add(deleteByIdListener);
}
public <R> R doWithDeleteByIdListener(Iterable<? extends C> entities, ThrowingExecutable<R, RuntimeException> delegate) {
R result;
try {
deleteByIdListener.beforeDeleteById(entities);
result = delegate.execute();
deleteByIdListener.afterDeleteById(entities);
} catch (RuntimeException e) {
deleteByIdListener.onDeleteError(entities, e);
throw e;
}
return result;
}
public void doWithDeleteByIdListener(Iterable<? extends C> entities, ThrowingRunnable<RuntimeException> delegate) {
try {
deleteByIdListener.beforeDeleteById(entities);
delegate.run();
deleteByIdListener.afterDeleteById(entities);
} catch (RuntimeException e) {
deleteByIdListener.onDeleteError(entities, e);
throw e;
}
}
public SelectListenerCollection<C, I> getSelectListener() {
return selectListener;
}
@Override
public void addSelectListener(SelectListener<? extends C, I> selectListener) {
this.selectListener.add(selectListener);
}
public Set<C> doWithSelectListener(Iterable<I> ids, ThrowingExecutable<Set<C>, RuntimeException> delegate) {
Set<C> result;
try {
selectListener.beforeSelect(ids);
result = delegate.execute();
selectListener.afterSelect(result);
} catch (RuntimeException e) {
selectListener.onSelectError(ids, e);
throw e;
}
return result;
}
/**
* Move internal listeners to given instance.
* Useful to aggregate listeners into a single instance.
* Please note that as this method is named "move" it means that listeners of current instance will be cleared.
*
* @param persisterListener the target listener on which the one of current instance must be moved to.
*/
public void moveTo(PersisterListenerCollection<C, I> persisterListener) {
this.persistListener.moveTo(persisterListener.persistListener);
this.insertListener.moveTo(persisterListener.insertListener);
this.updateByIdListener.moveTo(persisterListener.updateByIdListener);
this.updateListener.moveTo(persisterListener.updateListener);
this.deleteListener.moveTo(persisterListener.deleteListener);
this.deleteByIdListener.moveTo(persisterListener.deleteByIdListener);
this.selectListener.moveTo(persisterListener.selectListener);
}
}